package com.yanqu.road.server.gameplayer.module.activity.cat.action;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.cat.*;
import com.yanqu.road.pb.activity.CatProto;
import com.yanqu.road.server.gameplayer.module.activity.cat.ConnectResult;
import com.yanqu.road.server.manger.activity.cat.CatMgr;
import com.yanqu.road.server.pb.CatActivityPb;

import java.util.List;

public class DharmaElementAction extends BaseElementAction {

    public DharmaElementAction(int type) {
        super(type);
    }

    @Override
    boolean accept(Element element, Element next, ConnectResult context) {
        if(CatMgr.isBlock(next)){
            context.setRet(-1);
            return false;
        }
        int color = element.getColor();

        //下一个是监牢
        EleAttr attr = CatMgr.hasAttr(next, eElementAttrTypes.Prison.getType());
        if(attr != null){
            //颜色需要一致
            if(color != attr.getColor()) {
                context.setRet(-1);
                return false;
            }
            //连接数要大于血量
            if(attr.getVal() > context.getCurAttackPoint()){
                context.setRet(-1);
                return false;
            }
            //CatMgr.getLogger().info("-------- x:{},y:{}, 达摩——>监牢，扣血：{}/{}", next.getX(), next.getY(), attr.getVal(), context.getCurAttackPoint());
            context.setOffsetPoint(context.getOffsetPoint() + attr.getVal());
        }

        //下一个是达摩
        if(next.getType() == eElementTypes.Dharma.getType()){
            //颜色要一致
            if(color != next.getColor()){
                context.setRet(-1);
                return false;
            }
        }

        //下一个是小怪
        if(next.getType() == eElementTypes.Monster.getType()){
            //连接数要大于血量
            if(next.getVal() > context.getCurAttackPoint()){
                context.setRet(-1);
                return false;
            }
            //CatMgr.getLogger().info("-------- x:{},y:{}, 达摩——>小怪，扣血：{}/{}", next.getX(), next.getY(), next.getVal(), context.getCurAttackPoint());
            context.setOffsetPoint(context.getOffsetPoint() + next.getVal());
        }

        return super.acceptNext(context);
    }

    @Override
    void connect(Element element, ConnectResult context) {
        CatMgr.clearElementTypeInfo(element);
        CatMgr.removeElementAttr(element, eElementAttrTypes.Anger.getType());
        super.connectNext(context);
    }

    @Override
    void change(Element element, ConnectResult context) {
        onChange(element, context);
        super.changeNext(context);
    }

    public static void onChange(Element element, ConnectResult context){
        int index = CatMgr.getIndex(new Position(element.getX(), element.getY()));
        if(!context.getChangedList().contains(index)){
            //是否有香料盒
            EleAttr attr = CatMgr.hasAttr(element, eElementAttrTypes.SpiceBox.getType());
            if(attr != null){
                int old = attr.getId();
                if(element.getType() != eElementTypes.Role.getType()) {
                    attr.setId(attr.getId() == 401 ? 402 : 401);//开闭切换
                    //CatMgr.getLogger().info("----- 香料盒子  {}{}：{} to {}", element.getX(), element.getY(), old, attr.getId());
                }
            }
            //是否电车
            dianCheChange(element, context);
        }
    }

    public static void dianCheChange(Element element, ConnectResult context) {
        EleAttr attr1 = CatMgr.hasAttr(element, eElementAttrTypes.Tram.getType());
        if(attr1 != null){
            //方向是：1、上；2、下；3、左；4、右；5、顺时针；6、逆时针
            if(attr1.getVal() == 1){
                Element next = CatMgr.getElement(context.getElements(), element.getX(), element.getY() + 1);
                if(next == null || !move(element, context, next)){
                    next = CatMgr.getElement(context.getElements(), element.getX(), element.getY() - 1);
                    if(next != null){
                        move(element, context, next);
                        //方向置为相反
                        attr1.setVal(2);
                    }
                }
            }else if(attr1.getVal() == 2){
                Element next = CatMgr.getElement(context.getElements(), element.getX(), element.getY() - 1);
                if(next == null || !move(element, context, next)){
                    next = CatMgr.getElement(context.getElements(), element.getX(), element.getY() + 1);
                    if(next != null){
                        move(element, context, next);
                        //方向置为相反
                        attr1.setVal(1);
                    }
                }
            }else if(attr1.getVal() == 3){
                Element next = CatMgr.getElement(context.getElements(), element.getX() - 1, element.getY());
                if(next == null || !move(element, context, next)){
                    next = CatMgr.getElement(context.getElements(), element.getX() + 1, element.getY());
                    if(next != null){
                        move(element, context, next);
                        //方向置为相反
                        attr1.setVal(4);
                    }
                }
            }else if(attr1.getVal() == 4){
                Element next = CatMgr.getElement(context.getElements(), element.getX() + 1, element.getY());
                if(next == null || !move(element, context, next)){
                    next = CatMgr.getElement(context.getElements(), element.getX() - 1, element.getY());
                    if(next != null){
                        move(element, context, next);
                        //方向置为相反
                        attr1.setVal(3);
                    }
                }
            }else if(attr1.getVal() == 5){
                //逆时针
                //上左下右
                //如果有两个方向可以移动，则要取一个
                //当处于水平轨道的中间，或者垂直轨道的中间,(记住上一次移动的方向，继续沿用)
                List<Element> targetList = CatMgr.getFourDirection(context.getElements(), new Position(element.getX(), element.getY()));
                //移除没有轨道的
                targetList.removeIf(v -> CatMgr.hasAttr(v, eElementAttrTypes.Rail.getType()) == null);
                if(targetList.size() == 1){
                    Element next = targetList.get(0);
                    move(element, context, next);
                }else if(targetList.size() == 2){
                    Element next = targetList.get(1);
                    EleAttr eleAttr = CatMgr.hasAttr(element, eElementAttrTypes.LastMove.getType());
                    if(!lastMoveDriect(element, next, eleAttr == null ? 0 : eleAttr.getVal(), 5)){
                        next = targetList.get(0);
                        move(element, context, next);
                    }else {
                        move(element, context, next);
                    }
                }
            }else if(attr1.getVal() == 6){
                List<Element> targetList = CatMgr.getFourDirection(context.getElements(), new Position(element.getX(), element.getY()));
                targetList.removeIf(v -> CatMgr.hasAttr(v, eElementAttrTypes.Rail.getType()) == null);
                if(targetList.size() == 1){
                    Element next = targetList.get(0);
                    move(element, context, next);
                }else if(targetList.size() == 2){
                    Element next = targetList.get(0);
                    EleAttr eleAttr = CatMgr.hasAttr(element, eElementAttrTypes.LastMove.getType());
                    if(!lastMoveDriect(element, next, eleAttr == null ? 0 : eleAttr.getVal(), 6)){
                        next = targetList.get(1);
                        move(element, context, next);
                    }else {
                        move(element, context, next);
                    }
                }
            }
        }
    }

    //是否保持上次移动方向
    private static boolean lastMoveDriect(Element element, Element next, int val, int old) {
        if(val == 0){
            if(old == 5){
                if(element.getX() == next.getX()){
                    if(element.getX() <= 3){
                        return element.getY() < next.getY();
                    }else {
                        return element.getY() > next.getY();
                    }
                }
                if(element.getY() == next.getY()){
                    if(element.getY() <= 3){
                        return element.getX() > next.getX();
                    }else {
                        return element.getX() < next.getX();
                    }
                }
            }else if(old == 6){

            }
            return true;
        }else if(val == 1){
            return element.getY() < next.getY();
        }else if(val == 2){
            return element.getY() > next.getY();
        }else if(val == 3){
            return element.getX() > next.getX();
        }else if(val == 4){
            return element.getX() < next.getX();
        }
        return false;
    }

    /**
     * 电车移动
     */
    public static boolean move(Element element, ConnectResult context, Element next) {
        EleAttr attrTemp = CatMgr.hasAttr(next, eElementAttrTypes.Rail.getType());
        if(attrTemp == null){
            return false;
        }
        int tempX = element.getX();
        int tempY = element.getY();

        element.setX(next.getX());
        element.setY(next.getY());
        context.getElements()[element.getX()][element.getY()] = element;

        next.setX(tempX);
        next.setY(tempY);
        context.getElements()[next.getX()][next.getY()] = next;
        //CatMgr.getLogger().info("--------- next move {}, type {}, x {}, y {}", JSONObject.toJSONString(next.getAttrs()), next.getType(), next.getX(), next.getY());

        context.getChangedList().add(CatMgr.getIndex(new Position(element.getX(), element.getY())));

        //主角位置变化，需更新GameStatus
        if(element.getType() == eElementTypes.Role.getType()){
            context.getRolePosition().setX(element.getX());
            context.getRolePosition().setY(element.getY());
            context.getGameData().setRoleX(element.getX());
            context.getGameData().setRoleY(element.getY());
            //CatMgr.getLogger().info("--------- role move {}, type {}, x {}, y {}", JSONObject.toJSONString(element.getAttrs()), element.getType(), element.getX(), element.getY());
        }else {
            //CatMgr.getLogger().info("--------- other {} move {}, type {}, x {}, y {}", element.getType(), JSONObject.toJSONString(element.getAttrs()), element.getType(), element.getX(), element.getY());
        }

        //记住上次移动方向
        if(tempX == element.getX()){
            //上下移动
            if(element.getY() > tempY){
                //上
                addElementAttr(element, eElementAttrTypes.LastMove.getType(), 1);
            }else {
                //下
                addElementAttr(element, eElementAttrTypes.LastMove.getType(), 2);
            }
        }else if(tempY == element.getY()){
            //左右移动
            if(element.getX() > tempX){
                //右
                addElementAttr(element, eElementAttrTypes.LastMove.getType(), 4);
            }else {
                //左
                addElementAttr(element, eElementAttrTypes.LastMove.getType(), 3);
            }
        }

        int index = CatMgr.getIndex(new Position(tempX, tempY));
        int toIndex = CatMgr.getIndex(new Position(element.getX(), element.getY()));
        context.getMoveList().add(CatProto.CatGameMoveHistoryTemp.newBuilder().addIndex(index).addIndex(toIndex));
        CatMgr.getLogger().info("--------move {},{} to {},{}, {} to {}", tempX, tempY, element.getX(), element.getY(), index, toIndex);
        return true;
    }

    private static void addElementAttr(Element element, int type, int val) {
        EleAttr  eleAttr = CatMgr.hasAttr(element, type);
        if(eleAttr == null){
            eleAttr = new EleAttr();
            eleAttr.setType(type);
            eleAttr.setVal(val);
        }else {
            eleAttr.setVal(val);
        }

    }

    @Override
    void attack(Element element, ConnectResult context) {
        //小怪可能给达摩愤怒，这个愤怒状态的达摩当前回合不攻击
        int index = CatMgr.getIndex(new Position(element.getX(), element.getY()));
        if(!context.getChangedList().contains(index)){
            EleAttr eleAttr = CatMgr.hasAttr(element, eElementAttrTypes.Anger.getType());
            //愤怒的达摩
            if(eleAttr != null){
                List<Element> fourList = CatMgr.getFourDirection(context.getElements(), new Position(element.getX(), element.getY()));
                for (Element role : fourList) {
                    if(role.getType() == eElementTypes.Role.getType()){
                        if(role.getVal() > 0 && context.getGameData().getRoleBlood() > 0) {
                            //记录愤怒达摩伤害 detail
                            context.getDetailBuilderList().add(CatActivityPb.parseCatConnectDetailTemp(element.getX(), element.getY(), element.getType(), element.getId(), 1, 0));
                            role.setVal(role.getVal() - 1);
                            context.getGameData().setRoleBlood(context.getGameData().getRoleBlood() - 1);
                            //清除愤怒状态
                            CatMgr.removeElementAttr(element, eElementAttrTypes.Anger.getType());
                            CatMgr.getLogger().info("--------- 攻击主角：{}，{}", element.getX(), element.getY());

                            //主角掉血日志
                            int times = context.getGameData().getRoleBloodLose().getOrDefault(6, 0);
                            context.getGameData().getRoleBloodLose().put(6, times + 1);

                            //达摩技能发动日志
                            int times2 = context.getGameData().getMonsterSkill().getOrDefault(6, 0);
                            context.getGameData().getMonsterSkill().put(6, times2 + 1);
                        }
                    }
                }
            }
        }
        super.attackNext(context);
    }

    @Override
    void generate(Element element, ConnectResult context) {
        super.generateNext(context);
    }
}
